﻿using System;
using System.Diagnostics;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Phone.BackgroundAudio;

namespace WindowsPhoneAudioStreaming.Audio.Streaming.Agent
{
    /// <summary>
    /// A background agent that performs per-track streaming for playback
    /// </summary>
    public abstract class AudioTrackStreamer : AudioStreamingAgent
    {
        //
        // Set to true to use new ShoutCast stream source, false to use previous BufferedMediaStreamSource
        private bool useShoutcastStream = true;
        //
        //

        #region Variables
        private DispatcherTimer latestSongListTimer;
        private BufferedMediaStreamSource mediaSource;
        private ShoutCastStream shoutCastSource;
        private IAudioPlayerService nowPlayingService;
        private readonly Mutex progressMutex = new Mutex(false, "BufferProgress");
        #endregion

        protected abstract IAudioPlayerService InitializePlayingService();

        #region Methods
        /// <summary>
        /// Method fired when streaming begins
        /// </summary>
        /// <param name="track"></param>
        /// <param name="streamer"></param>
        protected override void OnBeginStreaming(AudioTrack track, AudioStreamer streamer)
        {
            nowPlayingService = InitializePlayingService();

            if (useShoutcastStream)
            {
                // Use the new shoutcast stream source to play an mp3 stream (note it will not parse .pls, .asx playlist files, needs to be the actual mp3 shoutcast stream)
                shoutCastSource = new ShoutCastStream(track.Tag);
                streamer.SetSource(shoutCastSource);

                // Event handler for when a track is complete or the user switches tracks
                shoutCastSource.StreamComplete += new EventHandler(StreamComplete);
            }
            else
            {
                // use the original stream source
                var streamSource = track.Tag;
                mediaSource = new BufferedMediaStreamSource(new Uri(streamSource), nowPlayingService);
                mediaSource.ErrorOnOpen += MediaSourceErrorOnOpen;
                streamer.SetSource(mediaSource);
            }

            progressMutex.WaitOne();
            try
            {
                track.BeginEdit();
                track.Tag = BufferStatus.Opening.ToString() + "|" + 0.0;
                track.EndEdit();
            }
            finally
            {
                progressMutex.ReleaseMutex();
            }


            Deployment.Current.Dispatcher.BeginInvoke(delegate
            {
                //Update the live tile every 30 seconds
                latestSongListTimer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(10)};
                latestSongListTimer.Tick += (s, e) => nowPlayingService.UpdatePlaylist();
                latestSongListTimer.Start();
            });

            nowPlayingService.UpdatePlaylist(true);
        }

        /// <summary>
        /// Method fired when there is an error opening the stream
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MediaSourceErrorOnOpen(object sender, EventArgs e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(delegate
            {
                if (latestSongListTimer != null)
                {
                    latestSongListTimer.Stop();
                }
            });
        }

        /// <summary>
        /// Called when the agent request is getting cancelled
        /// The call to base.OnCancel() is necessary to release the background streaming resources
        /// </summary>
        protected override void OnCancel()
        {
            base.OnCancel();
            if (latestSongListTimer != null)
            {
                latestSongListTimer.Stop();
            }

            Debug.WriteLine("AudioStreamer - OnCancel()");

            shoutCastSource.Shutdown();

            NotifyComplete();

        }

        /// <summary>
        /// Called when a track ends or the user switches tracks.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void StreamComplete(object sender, EventArgs e)
        {
            Debug.WriteLine("AudioStreamer - StreamComplete()");
            NotifyComplete();
        }
        
        #endregion
    }
}
